Skip to content

fix(attributes): make removeAttr case-insensitive in HTML mode#5290

Open
abhu85 wants to merge 1 commit into
cheeriojs:mainfrom
abhu85:fix/5257-removeattr-case-insensitive
Open

fix(attributes): make removeAttr case-insensitive in HTML mode#5290
abhu85 wants to merge 1 commit into
cheeriojs:mainfrom
abhu85:fix/5257-removeattr-case-insensitive

Conversation

@abhu85
Copy link
Copy Markdown

@abhu85 abhu85 commented Jun 6, 2026

Fixes #5257

Problem

htmlparser2 stores HTML attribute names in lowercase (per the HTML spec), but removeAttr looked them up using the caller-supplied casing. As a result, removeAttr('CLASS') failed to remove a parsed class attribute:

const $ = cheerio.load('<div class="test"></div>');
$('div').removeAttr('CLASS');
$('div').attr('class'); // 'test'  — expected undefined

Solution

Lowercase the attribute name before lookup when not in xmlMode, mirroring how the DOM treats HTML attribute names as case-insensitive. This follows the existing xmlMode convention already used by getAttr/setProp in this file.

  • HTML mode: removeAttr('CLASS') now removes a class attribute.
  • XML mode: casing is preserved (unchanged), since XML attribute names are case-sensitive.

The shared removeAttribute helper (also used by setAttr for null-value deletes) is intentionally left untouched, so programmatic case-sensitive behavior via attr(name, null) is unaffected.

Tests

Added two cases to .removeAttr:

  • HTML mode — uppercase name removes the lowercased attribute.
  • XML mode — a differently-cased name does not remove the attribute; the exact name still does.

Full suite: 792 passed, no type errors, lint clean.

htmlparser2 stores HTML attribute names in lowercase, but removeAttr
looked them up using the caller-supplied casing, so removeAttr('CLASS')
failed to remove a parsed `class` attribute. Lowercase the name before
lookup when not in xmlMode, matching the DOM's case-insensitive handling
of HTML attribute names. XML mode continues to preserve case.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 798fae029f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/api/attributes.ts

for (const attrName of attrNames) {
// HTML attribute names are case-insensitive; XML mode preserves case.
const lookup = this.options.xmlMode ? attrName : attrName.toLowerCase();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve mixed-case SVG attr removals

In default HTML mode Cheerio parses with parse5, which preserves/adjusts SVG foreign-content attribute names such as viewBox and preserveAspectRatio as mixed-case keys on elem.attribs; lowercasing every requested name when xmlMode is false makes $('svg').removeAttr('viewBox') look for viewbox instead and leave the parsed viewBox attribute in place. This affects common inline SVG markup even though the document is not in XML mode.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Bug: .removeAttr() should be case-insensitive for HTML documents

1 participant